package com.ndp.fb.walle.controller;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import com.ndp.ec.core.api.AudienceManagerService;
import com.ndp.fb.model.business.bo.targetingspec.CustomAudience;
import com.ndp.fb.model.business.bo.useraudience.result.FBTargetingSpecs;
import com.ndp.fb.walle.model.vo.useraudience.param.EcPreviewUserAudienceParam;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ndp.ec.core.FbUserService;
import com.ndp.ec.core.ProductSetService;
import com.ndp.fb.constant.CommonConstants;
import com.ndp.fb.enums.ErrorType;
import com.ndp.fb.exception.BusinessException;
import com.ndp.fb.exception.CheckedException;
import com.ndp.fb.rdb.api.AudienceManagerRdbService;
import com.ndp.fb.model.rdb.AudienceManager;
import com.ndp.fb.rdb.model.EntrustAccountExt;
import com.ndp.fb.rdb.model.FbUser;
import com.ndp.fb.rdb.model.Pager;
import com.ndp.fb.rdb.model.User;
import com.ndp.fb.rdb.model.UserAudienceTemplateLog;
import com.ndp.fb.walle.business.EntrustAccountService;
import com.ndp.fb.walle.business.UserAudienceService;
import com.ndp.fb.walle.business.UserAudienceTemplateService;
import com.ndp.fb.walle.model.bo.useraudience.result.PreviewUserAudienceResult;
import com.ndp.fb.walle.model.vo.OutputResult;
import com.ndp.fb.walle.model.vo.PageResult;
import com.ndp.fb.walle.model.vo.useraudience.param.AudienceManagerParam;
import com.ndp.fb.walle.model.vo.useraudience.param.SimpleUserAudienceParam;
import com.ndp.fb.walle.model.vo.useraudience.param.UserAudienceParam;
import com.ndp.fb.walle.util.ResponseUtils;

/**
 * Title: UserAudienceController.java Description: 用户定位控制层
 *
 * @author Administrator 创建时间 2014年7月16日 下午5:49:31
 */
@RequestMapping("/useraudiences")
@RestController
public class UserAudienceController {
	/**
	 * LOG日志
	 */
	private final org.slf4j.Logger LOG = LoggerFactory.getLogger(getClass());

	/**
	 * userAudienceService
	 */
	@Autowired
	private UserAudienceService userAudienceService;

	@Reference
	private FbUserService fbUserService;

	@Autowired
	private UserAudienceTemplateService userAudienceTemplateService;

	@Autowired
	private EntrustAccountService entrustAccountService;
	@Reference
	private AudienceManagerRdbService audienceManagerRdbService;
	@Reference
	private ProductSetService productSetService;

	@Reference
	private AudienceManagerService audienceManagerService;

	/**
	 * 预览用户定位
	 * 
	 * @param param
	 *            param
	 * @return ResponseEntity<String>
	 * @author Sisi 创建时间 2014年7月16日 下午5:53:18
	 */
	@RequestMapping(value = "previewUserAudience")
	@ResponseBody
	public ResponseEntity<String> previewUserAudience(@RequestParam(value = "param", required = true) String param,
			HttpServletRequest request) {
		ErrorType errorType = null;
		Map<String, Object> data = null;
		try {
			User user = (User) request.getSession().getAttribute("user");
			FbUser fbUser = fbUserService.getFbUser(user.getTicket());
			UserAudienceParam userAudienceParam = JSON.parseObject(param, UserAudienceParam.class);
			if (userAudienceParam != null && userAudienceParam.getUserAudienceTemplateId() > 0) {
				UserAudienceTemplateLog userAudienceTemplateLog = new UserAudienceTemplateLog();
				userAudienceTemplateLog.setFbConnectionObjectId(userAudienceParam.getFbConnectionObjectId());
				userAudienceTemplateLog.setProductConfId(userAudienceParam.getProductConfId());
				userAudienceTemplateLog.setUpdatedTime(new Date());
				userAudienceTemplateLog.setUserAudienceTemplateId(userAudienceParam.getUserAudienceTemplateId());
				userAudienceTemplateLog.setUserId(user.getTicket());
				userAudienceTemplateService.saveUserAudiceTemplateLog(userAudienceTemplateLog);
			}
			if (!StringUtils.hasText(userAudienceParam.getCacheId())
					|| !StringUtils.hasText(userAudienceParam.getTargetingSpecGroups())) {
				LOG.info("UserAudienceServiceImpl->previewUserAudiences->参数异常：" + userAudienceParam.toString());
				errorType = ErrorType.PARAM_EXCEPTION;
			} else {
				Integer groupCount = userAudienceService.previewUserAudiences(userAudienceParam, fbUser);
				data = new HashMap<>();
				data.put("groupCount", groupCount);
				data.put("publishCacheId", userAudienceParam.getCacheId());
			}
		} catch (BusinessException businessException) {
			errorType = businessException.getErrorType();
			LOG.error("UserAudienceController->previewUserAudience->", businessException);
		} catch (Exception e) {
			errorType = ErrorType.INTERNAL_EXCEPTION;
			LOG.error("UserAudienceController->previewUserAudience->", e);
		}

		OutputResult outputResult = ResponseUtils.bulidOutputResult(errorType, data);

		return ResponseUtils.returnJsonWithUTF8(JSON.toJSONString(outputResult));
	}

	/**
	 * 查询预览结果
	 * 
	 * @param param
	 * @return
	 */
	@RequestMapping(value = "searchPreviewUserAudienceResult")
	@ResponseBody
	public ResponseEntity<String> searchPreviewUserAudienceResult(
			@RequestParam(value = "param", required = true) String param) {
		ErrorType errorType = null;
		PreviewUserAudienceResult data = null;
		try {
			UserAudienceParam userAudienceParam = JSON.parseObject(param, UserAudienceParam.class);
			if (!StringUtils.hasText(userAudienceParam.getCacheId())) {
				LOG.info("UserAudienceServiceImpl->searchPreviewUserAudienceResult->参数异常："
						+ userAudienceParam.toString());
				errorType = ErrorType.PARAM_EXCEPTION;
			} else {
				data = userAudienceService.searchPreviewUserAudienceResult(userAudienceParam.getCacheId());
			}
			// }
		} catch (BusinessException businessException) {
			errorType = businessException.getErrorType();
			LOG.info("UserAudienceController->searchPreviewUserAudienceResult->", businessException);
		} catch (Exception e) {
			errorType = ErrorType.INTERNAL_EXCEPTION;
			LOG.error("UserAudienceController->searchPreviewUserAudienceResult->", e);
		}

		OutputResult outputResult = ResponseUtils.bulidOutputResult(errorType, data);

		return ResponseUtils.returnJsonWithUTF8(JSON.toJSONString(outputResult));
	}

	@RequestMapping(value = "previewSimpleUserAudience")
	@ResponseBody
	public ResponseEntity<String> previewSimpleUserAudience(
			@RequestParam(value = "param", required = true) String param, HttpServletRequest request) {
		ErrorType errorType = null;
		Map<String, Object> data = null;
		try {
			User user = (User) request.getSession().getAttribute("user");
			FbUser fbUser = fbUserService.getFbUser(user.getTicket());
			SimpleUserAudienceParam userAudienceParam = JSON.parseObject(param, SimpleUserAudienceParam.class);
			if (!StringUtils.hasText(userAudienceParam.getTargeting_spec())
					|| userAudienceParam.getAccount_id() == null) {
				LOG.info("UserAudienceServiceImpl->previewUserAudiences->参数异常：" + userAudienceParam.toString());
				errorType = ErrorType.PARAM_EXCEPTION;
			} else {
				String cacheId = userAudienceService.previewUserAudience(userAudienceParam.getTargeting_spec(), fbUser,
						userAudienceParam.getAccount_id());
				data = new HashMap<>();
				data.put("userAudienceCacheId", cacheId);
			}
		} catch (BusinessException businessException) {
			errorType = businessException.getErrorType();
			LOG.error("UserAudienceController->previewUserAudience->", businessException);
		} catch (Exception e) {
			errorType = ErrorType.INTERNAL_EXCEPTION;
			LOG.error("UserAudienceController->previewUserAudience->", e);
		}

		OutputResult outputResult = ResponseUtils.bulidOutputResult(errorType, data);

		return ResponseUtils.returnJsonWithUTF8(JSON.toJSONString(outputResult));
	}

	public static void main(String[] args) {
		String sst="{\"adAccountId\":\"1379662195604405\",\"audienceId\":\"\",\"productSetId\":\"7b2667df-b533-435b-8e8e-ca3951ff223e\",\"customAudiences\":[]}";
		EcPreviewUserAudienceParam previewUserAudienceParam=JSONObject.parseObject(sst,EcPreviewUserAudienceParam.class);
	}

	@RequestMapping(value = "previewEcSimpleUserAudience")
	public HashMap<String, String> previewEcSimpleUserAudience(@RequestBody EcPreviewUserAudienceParam param,
			HttpServletRequest request) throws CheckedException {
		User user = (User) request.getSession().getAttribute("user");
		FbUser fbUser = fbUserService.getFbUser(user.getTicket());

		JSONObject fbProdSet = productSetService.findOneFbProdSetIdByProductSetId(param.getProductSetId());
		Long fbProductsetId = fbProdSet.getLong("fb_productset_id");
		if (fbProductsetId == null) {
			String msg = "invalid fbProductSetId,不能预览用户定位。";
			LOG.error(msg);
			throw new CheckedException(msg);
		}
		AudienceManager template = audienceManagerRdbService.findById(param.getAudienceId());
		// String newTar=
		// template.getFbTargeting().replace("\"product_set_id.*\\,","\"product_set_id\":\""+productSetId+"\"");
		// 想用正则，为实现
		FBTargetingSpecs targetingSpec = JSON.parseObject(template.getFbTargeting(), FBTargetingSpecs.class);
		if (!CollectionUtils.isEmpty(targetingSpec.getProductAudienceSpecs())){
			targetingSpec.getProductAudienceSpecs().get(0).setProductSetId(fbProductsetId);
		}

		//自定义受众
		if (!CollectionUtils.isEmpty(param.getCustomAudiences())){
			List<CustomAudience> customAudiences = param.getCustomAudiences();
			List<CustomAudience> includes = new ArrayList<>();
			List<CustomAudience> excludes = new ArrayList<>();
			for (CustomAudience customAudience :customAudiences){
				if (customAudience.getIsClude()){
					includes.add(customAudience);
				} else {
					excludes.add(customAudience);
				}
				customAudience.setIsClude(null);
			}
			targetingSpec.setCustomAudiences(includes);
			targetingSpec.setExcludedCustomAudiences(excludes);
		}
		String newTargeting = JSON.toJSONString(targetingSpec);
		String cacheId;
		HashMap<String, String> data = new HashMap<>();
		ErrorType errorType;
		try {
			cacheId = userAudienceService.previewUserAudience(newTargeting, fbUser, param.getAdAccountId());
			data.put("userAudienceCacheId", cacheId);
		} catch (BusinessException businessException) {
			errorType = businessException.getErrorType();
			LOG.error("UserAudienceController->previewUserAudience->", businessException);
			data.put("error", errorType.getCode());
		} catch (Exception e) {
			errorType = ErrorType.INTERNAL_EXCEPTION;
			LOG.error("UserAudienceController->previewUserAudience->", e);
			data.put("error", errorType.getCode());
		}
		return data;
	}

	/**
	 * 查询预览结果
	 * 
	 * @param param
	 * @return
	 */
	@RequestMapping(value = "searchPreviewSimpleUserAudienceResult")
	@ResponseBody
	public ResponseEntity<String> searchPreviewSimpleUserAudienceResult(
			@RequestParam(value = "param", required = true) String param) {
		ErrorType errorType = null;
		PreviewUserAudienceResult data = null;
		try {
			SimpleUserAudienceParam userAudienceParam = JSON.parseObject(param, SimpleUserAudienceParam.class);
			if (!StringUtils.hasText(userAudienceParam.getUserAudienceCacheId())) {
				LOG.info("UserAudienceServiceImpl->searchPreviewUserAudienceResult->参数异常："
						+ userAudienceParam.toString());
				errorType = ErrorType.PARAM_EXCEPTION;
			} else {
				data = userAudienceService
						.searchPreviewSimpleUserAudienceResult(userAudienceParam.getUserAudienceCacheId());
			}
			// }
		} catch (BusinessException businessException) {
			errorType = businessException.getErrorType();
			LOG.info("UserAudienceController->searchPreviewUserAudienceResult->", businessException);
		} catch (Exception e) {
			errorType = ErrorType.INTERNAL_EXCEPTION;
			LOG.error("UserAudienceController->searchPreviewUserAudienceResult->", e);
		}

		OutputResult outputResult = ResponseUtils.bulidOutputResult(errorType, data);

		return ResponseUtils.returnJsonWithUTF8(JSON.toJSONString(outputResult));
	}

	@RequestMapping(value = "init")
	public ResponseEntity<String> init(@RequestBody AudienceManagerParam param, HttpServletRequest httpServletRequest) {
		ErrorType errorType = null;
		Map<String, Object> results = new HashMap<>();
		try {
			User user = (User) httpServletRequest.getSession().getAttribute("user");
			// 通过feed查找相应产品支持的账号
			List<EntrustAccountExt> entrustAccounts = entrustAccountService
					.findEntrustAccountsByUserId(user.getTicket());
			// 通过feed查询product_set
			List<Map<String, Object>> productSets = new ArrayList<>();
			results.put("accounts", entrustAccounts);
			results.put("productSets", productSets);
		} catch (Exception e) {
			LOG.error("UserAudienceController->init->", e);
			errorType = ErrorType.INTERNAL_EXCEPTION;
		}

		OutputResult outputResult = ResponseUtils.bulidOutputResult(errorType, results);

		return ResponseUtils.returnJsonWithUTF8(JSON.toJSONString(outputResult));
	}

	@RequestMapping(value = "save")
	public ResponseEntity<String> save(@RequestBody AudienceManager param, HttpServletRequest httpServletRequest) {
		ErrorType errorType = null;
		Long data = null;
		try {
			User user = (User) httpServletRequest.getSession().getAttribute("user");
			data = audienceManagerService.saveAudienceManager(user.getTicket(), param);
		} catch (CheckedException e) {
			errorType = e.getErrorType();
		} catch (Exception e) {
			LOG.error("UserAudienceController->save->", e);
			errorType = ErrorType.INTERNAL_EXCEPTION;
		}
		OutputResult outputResult = ResponseUtils.bulidOutputResult(errorType, data);
		return ResponseUtils.returnJsonWithUTF8(JSON.toJSONString(outputResult));
	}

	@RequestMapping(value = "listByUser")
	public ResponseEntity<String> list(@RequestBody AudienceManagerParam param, HttpServletRequest httpServletRequest) {
		Map<String, Object> results = new HashMap<>();
		ErrorType errorType = null;
		try {
			User user = (User) httpServletRequest.getSession().getAttribute("user");
			Integer sizeNo = param.getPSize() == null ? CommonConstants.DEFAULT_PAGE_SIZE_100 : param.getPSize();
			Integer firstResult = param.getCPage() == null ? 0 : (param.getCPage() - 1) * sizeNo;

			Pager<AudienceManager> ams = audienceManagerService.findByUserId(user.getTicket(), firstResult, sizeNo);
			if (ams == null) {
				ams = new Pager<>();
				ams.setPageIndex(sizeNo);
				ams.setTotalSize(0L);
			}
			// 计算分页结果
			long tSize = ams.getTotalSize();
			float nrOfPages = (float) tSize / sizeNo;
			int tPage = (int) ((nrOfPages > (int) nrOfPages || nrOfPages == 0.0) ? nrOfPages + 1 : nrOfPages);
			PageResult pageResult = new PageResult(tPage, param.getCPage(), param.getPSize(), tSize);
			results.put("list", ams.getResultList());
			results.put("paginator", pageResult);
		} catch (Exception e) {
			LOG.error("UserAudienceController->listByUser->", e);
			errorType = ErrorType.INTERNAL_EXCEPTION;
		}

		OutputResult outputResult = ResponseUtils.bulidOutputResult(errorType, results);
		return ResponseUtils.returnJsonWithUTF8(JSON.toJSONString(outputResult));
	}

	@RequestMapping(value = "listByFeed")
	public ResponseEntity<String> listByFeed(@RequestBody AudienceManagerParam param) {
		Map<String, Object> results = new HashMap<>();
		ErrorType errorType = null;
		try {
			Integer sizeNo = param.getPSize() == null ? CommonConstants.DEFAULT_PAGE_SIZE_100 : param.getPSize();
			Integer firstResult = param.getCPage() == null ? 0 : (param.getCPage() - 1) * sizeNo;

			Pager<AudienceManager> ams = audienceManagerService.findByFeed(param.getWeFeedId(), firstResult, sizeNo);
			if (ams == null) {
				ams = new Pager<>();
				ams.setPageIndex(sizeNo);
				ams.setTotalSize(0L);
			}
			// 计算分页结果
			long tSize = ams.getTotalSize();
			float nrOfPages = (float) tSize / sizeNo;
			int tPage = (int) ((nrOfPages > (int) nrOfPages || nrOfPages == 0.0) ? nrOfPages + 1 : nrOfPages);
			PageResult pageResult = new PageResult(tPage, param.getCPage(), param.getPSize(), tSize);
			results.put("list", ams.getResultList());
			results.put("paginator", pageResult);
		} catch (Exception e) {
			LOG.error("UserAudienceController->listByUser->", e);
			errorType = ErrorType.INTERNAL_EXCEPTION;
		}

		OutputResult outputResult = ResponseUtils.bulidOutputResult(errorType, results);
		return ResponseUtils.returnJsonWithUTF8(JSON.toJSONString(outputResult));
	}

	@RequestMapping(value = "listAllByFeed")
	public List<AudienceManager> listAllByFeed(@RequestParam(value = "weFeedId", required = true) Long weFeedId) {
		return audienceManagerService.findAllByFeed(weFeedId);
	}

	/**
	 * 用于校验用户定位的产品系列列表
	 * 
	 * @return
	 */
	@RequestMapping(value = "validateProductSetList")
	public ResponseEntity<String> validateProductSetList(@RequestBody AudienceManagerParam param,
			HttpServletRequest httpServletRequest) {
		ErrorType errorType = null;
		Map<String, Object> results = null;
		try {
			User user = (User) httpServletRequest.getSession().getAttribute("user");
			results = userAudienceService.validateProductSetList(user.getTicket(), param.getWeFeedId());
		} catch (Exception e) {
			LOG.error("UserAudienceController->init->", e);
			errorType = ErrorType.INTERNAL_EXCEPTION;
		}
		OutputResult outputResult = ResponseUtils.bulidOutputResult(errorType, results);
		return ResponseUtils.returnJsonWithUTF8(JSON.toJSONString(outputResult));
	}

	/**
	 * 查询受众
	 *
	 * @return
	 */
	@RequestMapping(value = "findById")
	public AudienceManager findById(@RequestParam(value = "id", required = true) Long id) {
		return audienceManagerRdbService.findById(id);
	}
}
